package main

import (
	"crypto/rc4"
	"fmt"
)

// Alice and Bob
// Get the same key and create the same cipher
// Then transport message
// Alice: Hi, Bob.
// Bob: Hi, Alice.
// Bob: How are u ? (dog)
// Alice: Fine! Thank u. And u ? (dog)

type Student struct {
	Name string

	encryper  *rc4.Cipher
	encrypKey string

	decryper  *rc4.Cipher
	decrypKey string
}

func NewStudent(name string, encrypKey, decrypKey string) *Student {
	encryper, err := rc4.NewCipher([]byte(encrypKey))
	if err != nil {
		panic(err)
	}
	decryper, err := rc4.NewCipher([]byte(decrypKey))
	if err != nil {
		panic(err)
	}
	return &Student{
		Name:      name,
		encryper:  encryper,
		encrypKey: encrypKey,
		decryper:  decryper,
		decrypKey: decrypKey,
	}
}

func (this *Student) Speak(plaintext []byte) []byte {
	fmt.Printf("%s Speak: %s\n", this.Name, string(plaintext))
	this.encryper.XORKeyStream(plaintext, plaintext)
	return plaintext
}

func (this *Student) Hear(ciphertext []byte) {
	this.decryper.XORKeyStream(ciphertext, ciphertext)
	fmt.Printf("%s Hear: %s\n", this.Name, string(ciphertext))
}

func main() {
	// Normally, We have to use a method of securely exchanging cryptographic keys over a public channel
	// Like [Diffie-Hellman key exchange](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)
	// But, Diffie-Hellman key exchange was thus vulnerable to a man-in-the-middle attack

	key1, key2 := "cipher1", "cipher2"
	alice := NewStudent("Alice", key1, key2)
	bob := NewStudent("Bob", key2, key1)

	bob.Hear(alice.Speak([]byte("Hi, Bob.")))
	c1 := bob.Speak([]byte("Hi, Alice."))
	c2 := bob.Speak([]byte("How are u ? (dog)"))
	alice.Hear(c1)
	alice.Hear(c2)
	bob.Hear(alice.Speak([]byte("Fine! Thank u. And u ? (dog)")))
}
